package com.wanho.qz103.hrsaas.sys.service.impl;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.wanho.qz103.hrsaas.commons.annontations.Autowired;
import com.wanho.qz103.hrsaas.commons.annontations.Service;
import com.wanho.qz103.hrsaas.commons.annontations.Transactional;
import com.wanho.qz103.hrsaas.commons.exception.DAOException;
import com.wanho.qz103.hrsaas.commons.exception.ServiceException;
import com.wanho.qz103.hrsaas.commons.query.Page;
import com.wanho.qz103.hrsaas.commons.util.JwtUtils;
import com.wanho.qz103.hrsaas.commons.util.MD5Util;
import com.wanho.qz103.hrsaas.commons.vo.TableVO;
import com.wanho.qz103.hrsaas.sys.dao.EmployeeDAO;
import com.wanho.qz103.hrsaas.sys.dao.PermissionDAO;
import com.wanho.qz103.hrsaas.sys.dao.RoleDAO;
import com.wanho.qz103.hrsaas.sys.dao.UserDAO;
import com.wanho.qz103.hrsaas.sys.pojos.Employee;
import com.wanho.qz103.hrsaas.sys.pojos.Permission;
import com.wanho.qz103.hrsaas.sys.pojos.Role;
import com.wanho.qz103.hrsaas.sys.pojos.User;
import com.wanho.qz103.hrsaas.sys.service.UserService;
import com.wanho.qz103.hrsaas.sys.vo.UserInfoVO;
import com.wanho.qz103.hrsaas.sys.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.converters.DateConverter;

import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
@Slf4j
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDAO userDAO ;
    @Autowired
    private PermissionDAO permissionDAO ;
    @Autowired
    private RoleDAO roleDAO ;
    @Autowired
    private EmployeeDAO employeeDAO ;

    @Override
    public boolean modify(Map<String, String[]> parameterMap) throws ServiceException {
        try {
            //根据id查询用户对象
            String id = parameterMap.get("id")[0];
            //从数据库中捞出 user对象
            User dbUser = userDAO.selectById(id);
            // 映射请求参数对象
            User paramUser = new User();
            // 注册 日期类型转换器  把用户输入的日期 转成 Date类型
            ConvertUtils.register(new Converter() {
                                      @Override
                                      public Object convert(Class clazz, Object value) {
                                          //将String转化为date
                                          SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                                          Date parse=null;
                                          try {
                                              //parse()返回的是一个Date类型数据，format返回的是一个StringBuffer类型的数据
                                              parse =format.parse(value.toString());
                                          } catch (ParseException e) {
                                              e.printStackTrace();
                                          }
                                          return parse;
                                      }
                                  }, java.util.Date.class);
            BeanUtils.populate(paramUser,parameterMap);
            //设置 前端没有传递的参数： 盐值 salt
            paramUser.setSalt(dbUser.getSalt());
            //判断 是否拥有请求参数  password2 如果有该参数名 用户修改密码
            if (parameterMap.containsKey("password2")){
                //对 输入框明文密码 加密
                String password2 = MD5Util.md5(parameterMap.get("password2")[0], dbUser.getSalt());
                //设置密码 修改新密码
                paramUser.setPassword(password2);
            }
            return userDAO.update(paramUser);
        } catch (DAOException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            throw new ServiceException("更新用户基本信息异常！") ;
        }
    }


    @Override
    public boolean importExcel(List<User> userList) throws ServiceException {
        try {
            List<Employee> employeeList = userList.stream().map(User::getEmployee).collect(Collectors.toList());
            //批量插入 员工信息表
            boolean insertEmployeeBatch = employeeDAO.insertBatch(employeeList);
            //批量插入 用户基本信息表
            boolean insertUserBatch = userDAO.insertBatch(userList);
            return insertEmployeeBatch && insertUserBatch ;
        } catch (DAOException e) {
            e.printStackTrace();
            throw new ServiceException("批量导入员工数据异常！");
        }
    }

    @Override
    public TableVO selectPage(Page page) throws ServiceException {
        try {
            TableVO tableVO = new TableVO();
            //统计 总记录数
            long count = userDAO.selectCount();
            // 查询当前页
            if (count!=0){
                page.setOffset((page.getPage()-1)*page.getSize());
                List<User> userList = userDAO.selectTopN(page);
                tableVO.setRows(userList);
            }
            // 封装 tableVO
            tableVO.setTotal(count);
            return tableVO ;
        } catch (DAOException e) {
            e.printStackTrace();
            throw new ServiceException("获得员工列表异常！") ;
        }
    }

    @Override
    public List<User> getSimple() throws ServiceException {
        try {
            return userDAO.selectAll();
        } catch (DAOException e) {
            e.printStackTrace();
            throw new ServiceException("获得用户简单列表失败！！！") ;
        }
    }

    @Override
    public UserInfoVO getUserInfo(String userId) throws ServiceException {
        try {
            //1.获得用户基本信息
            User user = userDAO.selectById(userId);
            //2.获得用户角色id
            List<Role> roleList = roleDAO.selectByUserId(userId);
            List<String> roleIdList = roleList.stream().map(Role::getId).collect(Collectors.toList());
            //3. 创建对象
            UserInfoVO userInfoVO = new UserInfoVO();
            //4. 拷贝同名属性
            BeanUtils.copyProperties(userInfoVO,user);
            //5. 设置关联角色
            userInfoVO.setRoleIds(roleIdList);
            return userInfoVO;
        } catch (DAOException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            throw new ServiceException("获得用户详情异常！！！") ;
        }
    }

    @Override
    public UserVO getProfile(String token) throws ServiceException {
        try {
            // 去掉 Bearer
            token = token.substring("Bearer ".length()) ;
            // 调用工具类 进行 获得 用户id
            DecodedJWT tokenInfo = JwtUtils.getTokenInfo(token);
            String userId = tokenInfo.getClaim("userId").as(String.class);
            //1.获得用户基本信息
            User user = userDAO.selectById(userId);
            //2. 获得用户权限信息 apis menus  points
            List<Permission> permissionList = permissionDAO.selectByUserId(userId);
            // 根据权限类型 菜单权限  code
            List<String> menus = permissionList.stream().filter(permission -> permission.getType().equals(1)).map(Permission::getCode).collect(Collectors.toList());
            // 按钮权限 code
            List<String> points = permissionList.stream().filter(permission -> permission.getType().equals(2)).map(Permission::getCode).collect(Collectors.toList());
            // apis 权限 暂时不做处理
            // 封装 UserVO 对象  属性空值 默认值
            UserVO userVO = new UserVO();
            // 对象属性拷贝  user 从数据库捞出的对象 属性 拷贝到 userVo对象中
            BeanUtils.copyProperties(userVO,user);
            //解决 不同名的id 赋值问题？
            userVO.setUserId(user.getId());
            userVO.getRoles().setMenus(menus);
            userVO.getRoles().setPoints(points);
            return userVO ;
        } catch (DAOException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            throw new ServiceException("查询用户基本信息异常！！！"+e.getMessage()) ;
        }
    }

    @Override
    public String login(String mobile, String password) throws ServiceException {
        try {
            // 根据手机号码查询
            User user = userDAO.selectByMobile(mobile);
            log.debug("根据手机号["+mobile+"]查询的用户对象:"+user);
            // 手机号码错误
            if (user==null) {
                return null;
            }
            // 获得盐值  密文
            String salt = user.getSalt();
            String dbMd5Password = user.getPassword();
            // 把用户输入的密码 进行md5加密
            String inputMd5Password = MD5Util.md5(password, salt);
            // 密码错误
            if (!inputMd5Password.equals(dbMd5Password)){
                return null ;
            }
            // 返回token
            Map<String,String> map = new HashMap<>();
            map.put("userId",user.getId()) ;
            String jwtToken = JwtUtils.createJwtToken(map);
            return jwtToken ;
        } catch (DAOException e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage()) ;
        }
    }
}
